/*
 * Created on May 8, 2004
 *
 * Vectrics Inc.  GNU Public License.
 */
package org.vectrics.hibernate;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

/**
 * @author mmoore
 */
public class SqlFilter {
	private Collection fields = new HashSet();
	private Collection conditions = new HashSet();
	private Collection froms = new HashSet();
	private Collection orderBys = new HashSet();
	
	/**
	 * 
	 */
	public SqlFilter() {
		super();
	}
	
	public void addFrom(String objectName, String instanceName) {
		froms.add(objectName + " " + instanceName);
	}
	
	private String getFromSection() {
		String fieldSection = "";
		Iterator iter = froms.iterator();
		while (iter.hasNext()) {
			String field = (String)iter.next();
			fieldSection += field;
			if (iter.hasNext()) {
				fieldSection += ", ";
			}
		}
		if (fieldSection.trim().length() <= 0)
			fieldSection = null;
		return(fieldSection);
	}
	
	public void addOrderBy(String field) {
		orderBys.add(field);
	}
	
	private String getOrderBysSection() {
		String fieldSection = "";
		Iterator iter = orderBys.iterator();
		while (iter.hasNext()) {
			String field = (String)iter.next();
			fieldSection += field;
			if (iter.hasNext()) {
				fieldSection += ", ";
			}
		}
		if (fieldSection.trim().length() <= 0)
			fieldSection = null;
		return(fieldSection);
	}
	
	
	public void addCondition(String condition) {
		conditions.add(condition);
	}
	
	public void addStringCondition(String field, String value) {
		String sqlValue = value;
		boolean patternMatchUsed = false;
		while (sqlValue.indexOf("*") >= 0) {
			patternMatchUsed = true;
			int pos = sqlValue.indexOf("*");
			String prefix = "";
			String suffix = "";
			if (pos > 0) {
				prefix = sqlValue.substring(0, pos);
			}
			sqlValue += "%";
			if (pos != (value.length()  - 1)) {
				suffix = sqlValue.substring(pos + 1);
			}
			sqlValue = prefix + "%" + suffix;
		}
		if (patternMatchUsed) {
			this.addCondition(field + " like '" + sqlValue + "'");
		}
		else {
			this.addCondition(field + " = '" + sqlValue + "'");
		}
	}
	
	
	public void addField(String field) {
		fields.add(field);
	}
	
	private String getFieldSection() {
		String fieldSection = "";
		Iterator iter = fields.iterator();
		while (iter.hasNext()) {
			String field = (String)iter.next();
			fieldSection += field;
			if (iter.hasNext()) {
				fieldSection += ", ";
			}
		}
		if (fieldSection.trim().length() <= 0)
			fieldSection = null;
		return(fieldSection);
	}
	
	private String getConditionSection() {
		String conditionSection = null;

		
		Iterator iter = conditions.iterator();
		if (iter.hasNext()) {
			conditionSection = "";
			while (iter.hasNext()) {
				String condition = (String)iter.next();
				conditionSection += "(";
				conditionSection += condition;
				conditionSection += ")";
				if (iter.hasNext()) {
					conditionSection += " and ";
				}
			}
			if (conditionSection.trim().length() <= 0)
				conditionSection = null;
		}
		
		return(conditionSection);
	}
	
	
	public String getStatement() throws SqlFilterNotValidException {
		StringBuffer statement = new StringBuffer();
		
		String fieldSection = getFieldSection();
		if (fieldSection == null)
			throw new SqlFilterNotValidException("Missing fields");

		statement.append("select ");
		String conditionSection = this.getConditionSection();
		statement.append(fieldSection);
		statement.append(" from");
		if (froms.size() == 0)
			throw new SqlFilterNotValidException("No 'from' clauses were added to the filter");
		statement.append(" ");
		statement.append(this.getFromSection());
		
		String conditionsSection = this.getConditionSection();
		if (conditionsSection != null) {
			statement.append(" where ");
			statement.append(conditionsSection);
		}
		
		if (orderBys.size() > 0) {
			statement.append(" order by ");
			statement.append(this.getOrderBysSection());
		}
		
		return(statement.toString());
	}

}
